package com.xiashitech.agent.instrumentation.db.statement.sanitizer.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xiashitech.agent.cache.data.CacheData;
import com.xiashitech.agent.cache.data.CacheSync;
import com.xiashitech.agent.config.StartConfig;
import com.xiashitech.agent.constants.SpecialConfigString;
import com.xiashitech.agent.grpc.XsAuthFactClient;
import com.xiashitech.agent.instrumentation.log.XSLevel;
import com.xiashitech.agent.utils.XiashiGrpcUtil;
import com.xiashitech.agent.utils.HttpUtil;
import com.xiashitech.agent.utils.JsonUtil;
import com.xiashitech.interfaces.agent.dto.AgentConfigDTO;
import com.xiashitech.interfaces.apiservice.UserTracingMsg;
import com.xiashitech.interfaces.apiservice.dto.AuthFactRequest;
import com.xiashitech.interfaces.apiservice.dto.AuthFactResponse;
import io.opentelemetry.javaagent.shaded.instrumentation.api.db.SqlDialect;
import io.opentelemetry.javaagent.shaded.instrumentation.api.db.SqlStatementInfo;
import io.opentelemetry.javaagent.shaded.instrumentation.api.db.SqlStatementSanitizer;

import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.logging.Logger;

public class XSSqlSanitizer implements UserTracingMsg {
    private static final Logger logger = Logger.getLogger(XSSqlSanitizer.class.getName());
    public XSSqlSanitizer() {
    }
    private static final SqlStatementSanitizer sanitizer = SqlStatementSanitizer.create(true);
    public SqlStatementInfo sanitize(@Nullable String statement) {
        return sanitizer.sanitize(statement, SqlDialect.DEFAULT);
    }

    @Override
    public AuthFactResponse supplementUserTracing(AuthFactRequest authFactRequest) {
        if (authFactRequest == null) {
            return null;
        }
        try {
            CacheData cacheData = CacheSync.getInstance().getCacheData(authFactRequest);
            if(cacheData != null) {
                return (AuthFactResponse)cacheData.getReturnValue();
            }
            String appCode  = AgentConfigDTO.getConfig().getSystemAppCode().get(SpecialConfigString.STOPAUTH_SYSTEMID.getConfiString());
            if(appCode == null) {
                CacheSync.getInstance().init(XSSqlSanitizer.class, "supplementUserTracingForJob", authFactRequest, null);
                return null;
            }
            if(!appCode.isEmpty()) {
                String[] appCodeArray = appCode.split(",");
                boolean isStop = Arrays.stream(appCodeArray).anyMatch(item-> item.equalsIgnoreCase(StartConfig.getParamValueFromKey(StartConfig.systemId)));
                if (isStop) {
                    CacheSync.getInstance().init(XSSqlSanitizer.class, "supplementUserTracingForJob", authFactRequest, null);
                    return null;
                }
            }
            if(XiashiGrpcUtil.useGrpc()) {
                // 加入缓存，用户在推送通道断了后，能重建
                CacheSync.getInstance().init(XSSqlSanitizer.class, "supplementUserTracingForJob", authFactRequest, null);
                // 如果是 Grpc，需要发起请求，建立服务端推送通道
                supplementUserTracingForJob(authFactRequest);
            } else {
                ObjectMapper objectMapper = new ObjectMapper();
                String param = objectMapper.writeValueAsString(authFactRequest);
                String response = HttpUtil.doPost(AgentConfigDTO.getConfig().getAuthservice(), param, "application/json;charset=utf-8");
                if (response != null && !response.isEmpty() && JsonUtil.isJson(response)) {
                    AuthFactResponse authFactResponse = JsonUtil.convertStringToObject(response, AuthFactResponse.class);
                    if (cacheData == null) {
                        CacheSync.getInstance().init(XSSqlSanitizer.class, "supplementUserTracingForJob", authFactRequest, authFactResponse);
                    }
                    return authFactResponse;
                }
            }
        } catch (Throwable e) {
            logger.log(XSLevel.DEBUG, "The Agent fails to obtain database permission information from Agentservice.");
            StartConfig.throwableStackPrinter(e);
        }
        CacheSync.getInstance().init(XSSqlSanitizer.class, "supplementUserTracingForJob", authFactRequest, null);
        return null;
    }

    @Override
    public AuthFactResponse supplementUserTracingForJob(AuthFactRequest authFactRequest) {
        if (authFactRequest == null) {
            return null;
        }
        try {
            if (XiashiGrpcUtil.useGrpc()) {
                // 异步方式，不直接返回，这里会返回 null，后续逻辑会略过 null 的处理，无影响
                XsAuthFactClient.getClient().supplementUserTracingGRPC(authFactRequest);
            } else {
                ObjectMapper objectMapper = new ObjectMapper();
                String param = objectMapper.writeValueAsString(authFactRequest);
                String response = HttpUtil.doPost(AgentConfigDTO.getConfig().getAuthservice(), param, "application/json;charset=utf-8");
                if (response != null && !response.isEmpty() && JsonUtil.isJson(response)) {
                    AuthFactResponse authFactResponse = JsonUtil.convertStringToObject(response, AuthFactResponse.class);
                    return authFactResponse;
                }
            }
        } catch (Throwable e) {
            logger.log(XSLevel.DEBUG, "The Agent fails to obtain database permission information from Agentservice for cache.");
        }
        return null;
    }
}
